package com.ruoyi.framework.aspectj;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.annotation.JoException;
import com.ruoyi.common.exception.ServiceException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 操作日志记录处理
 *
 * @author ruoyi
 */
@Order(0)
@Aspect
@Component
public class JoExceptionAspect
{
    private static final Logger log = LoggerFactory.getLogger(JoExceptionAspect.class);

    /**
     * 拦截异常操作
     *
     * @param joinPoint 切点
     * @param e         异常
     */
    @AfterThrowing(value = "@annotation(joException)", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, JoException joException, Exception e)
    {
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        // 获取堆栈跟踪数组
        StackTraceElement[] stackTrace = e.getStackTrace();
        // 通常，第一个元素是捕获异常的代码行，第二个元素是引发异常的代码行
        // StackTraceElement element = stackTrace[1];

        // 日志信息
        log.error("[{}.{}]:[{}{}:{}](e:{})", className, methodName,
                joException.message(), joException.cause(),
                ObjectUtil.isNotEmpty(stackTrace) ? stackTrace[1].getLineNumber() : "(0)",
                e.getMessage());

        //抛出异常处理
        if (e instanceof ServiceException)
        {
            throw new ServiceException(e.getMessage(), joException.code());
        }

        //拦截异常处理
        if (StrUtil.isNotEmpty(joException.message()))
        {
            //有配置异常消息
            throw new ServiceException(joException.message(), joException.code());
        }

        //没有配置异常消息，默认使用异常枚举
        throw new ServiceException(joException.cause());
    }

}
